package net.zoneland.zrdp.web.impl;

import javax.servlet.http.HttpServletRequest;

import net.zoneland.springboot.async.AsyncHelper;
import net.zoneland.springboot.config.SharedAppConfig;
import net.zoneland.springboot.redis.AbstractAppHttpSessionManager;
import net.zoneland.springboot.session.AppHttpSessionAdapter;
import net.zoneland.springboot.spi.FeatureSwitchableProvider;
import net.zoneland.zrdp.common.core.domain.model.LoginUser;
import net.zoneland.zrdp.framework.web.service.TokenService;

//-Dapp.server-pub-sub.appHttpSessionManagerClass=net.zoneland.zrdp.web.impl.ZrdpAppHttpSessionManager
public class ZrdpAppHttpSessionManager extends AbstractAppHttpSessionManager implements FeatureSwitchableProvider {

    @Override
    public <T> T getSessionAttribute(final HttpServletRequest request, final String name) {
        final LoginUser loginUser = getLoginUser(request);
        if (loginUser == null) {
            return null;
        }
        return loginUser.findSessionAttribute(name);
    }

    private TokenService tokenService;

    private LoginUser getLoginUser(final HttpServletRequest request) {
        return getTokenService().getLoginUser(request, false);
    }

    private TokenService getTokenService() {
        if (tokenService == null) { //此特为解决初台化循环依赖问题,特意不用@Autowired
            tokenService = SharedAppConfig.getBean(TokenService.class);
        }
        return tokenService;
    }

    @Override
    public <T> void setSessionAttribute(final HttpServletRequest request, final String name, final T value) {
        final LoginUser loginUser = getLoginUser(request);
        if (loginUser == null) {
            return;
        }
        loginUser.getSessionData().put(name, value);
        storeUser(loginUser);
    }

    @Override
    public AppHttpSessionAdapter getAppHttpSessionAdapter(final HttpServletRequest request) {
        final LoginUser loginUser = getLoginUser(request);
        return new ZrdpAppHttpSessionAdapter(loginUser);
    }

    private void storeUser(final LoginUser user) {
        final String taskId = "store-user-" + user.getToken();
        AsyncHelper.submitTask(taskId, 0, () -> {
            tokenService.refreshToken(user);
            return null;
        });
    }

    public class ZrdpAppHttpSessionAdapter implements AppHttpSessionAdapter {

        private final LoginUser target;

        public ZrdpAppHttpSessionAdapter(final LoginUser target) {
            this.target = target;
        }

        @Override
        public <T> T getAttribute(final String name) {
            return target == null ? null : target.findSessionAttribute(name);
        }

        @Override
        public <T> void setAttribute(final String name, final T value) {
            if (target == null) {
                return;
            }
            target.putSessionAttribute(name, value);
            storeUser(target);
        }

        @Override
        public void removeAttribute(final String name) {
            if (target == null) {
                return;
            }
            target.getSessionData().remove(name);
            storeUser(target);
        }
    }

    @Override
    public boolean isFeatureOn() {
        return getTokenService().isCacheOnJvm();
    }

    /**
     * 原如的cacheOnJvm状态,用于恢复原状态时使用.
     */
    private Boolean srcCacheOnJvmFlag;

    @Override
    public boolean enableFeature(final Boolean enable) {
        final TokenService service = getTokenService();
        if (srcCacheOnJvmFlag == null) {
            srcCacheOnJvmFlag = service.isCacheOnJvm();
        }
        return service.setCacheOnJvm(enable == null ? srcCacheOnJvmFlag : enable);
    }

    @Override
    public String getFeatureProviderId() {
        return "app-user-cache-in-jvm";
    }
}
